package cn.spike.rockcc.service.impl;

import cn.spike.rockcc.domain.KillActivity;
import cn.spike.rockcc.domain.KillCourse;
import cn.spike.rockcc.errorenum.GlobalExceptionCode;
import cn.spike.rockcc.mapper.KillActivityMapper;
import cn.spike.rockcc.service.IKillActivityService;
import cn.spike.rockcc.service.IKillCourseService;
import cn.spike.rockcc.util.AssertUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author spike
 * @since 2023-03-25
 */
@Service
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {

    @Autowired
    private IKillCourseService killCourseService;

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    /**
     * 发布活动 修改状态 添加进redis 添加信号量
     * @param id
     */
    @Override
    @Transactional
    public void publish(Long id) {
        KillActivity killActivity = super.selectById(id);
        AssertUtil.isNotNull(killActivity, GlobalExceptionCode.ACTIVITY_EXCEPTION);
        //判断发布秒杀活动的时间是否在活动结束时间之前
        boolean b = new Date().before(killActivity.getEndTime());
        //如果发布在秒杀活动结束时间之后 - 抛异常
        AssertUtil.isTrue(b,GlobalExceptionCode.ACTIVITY_IS_OVER_EXCEPTION);
        //查找该秒杀活动下的所有秒杀课程
        Wrapper<KillCourse> wrapper = new EntityWrapper<>();
        wrapper.eq("activity_id",id);
        List<KillCourse> killCourses = killCourseService.selectList(wrapper);
        AssertUtil.isNotNull(killCourses,GlobalExceptionCode.NOT_HAVE_KILLCOURSE_EXCEPTION);
        //修改状态 - 将数据保存到redis中
        killActivity.setPublishTime(new Date());
        killActivity.setPublishStatus(KillActivity.PUBLISHING);
        for (KillCourse killCourse : killCourses) {
            killCourse.setPublishTime(new Date());
            killCourse.setPublishStatus(KillCourse.KILLING);
            //将数据保存到redis中
            redisTemplate.opsForHash().put(
               "activity:"+id,killCourse.getId().toString(),killCourse);
            //使用redisson设置信号量
            RSemaphore semaphore = redissonClient.getSemaphore(killCourse.getId().toString());
            boolean b1 = semaphore.trySetPermits(killCourse.getKillCount());
            AssertUtil.isTrue(b1,GlobalExceptionCode.REDISSON_EXCEPTION);
        }
        super.updateById(killActivity);
        killCourseService.updateBatchById(killCourses);
    }
}
